From 725595e667cc4423347c255da8ca4c5b3aa0980a Mon Sep 17 00:00:00 2001
From: Vincent Chen <vincent.chen@sifive.com>
Date: Mon, 15 Nov 2021 03:31:04 -0800
Subject: [PATCH 2/8] board: sifive: spl: Initialized the PWM setting in the
 SPL stage

LEDs and multiple fans can be controlled by SPL. This patch ensures
that all fans have been enabled in the SPL stage. In addition, the
LED's color will be set to yellow.
---
 board/sifive/unmatched/Makefile |  1 +
 board/sifive/unmatched/pwm.c    | 57 +++++++++++++++++++++++++++++++++
 board/sifive/unmatched/spl.c    |  2 ++
 3 files changed, 60 insertions(+)
 create mode 100644 board/sifive/unmatched/pwm.c

diff --git a/board/sifive/unmatched/Makefile b/board/sifive/unmatched/Makefile
index 1345330089..5df01982e9 100644
--- a/board/sifive/unmatched/Makefile
+++ b/board/sifive/unmatched/Makefile
@@ -9,3 +9,4 @@ obj-y += spl.o
 else
 obj-y += unmatched.o
 endif
+obj-y += pwm.o
diff --git a/board/sifive/unmatched/pwm.c b/board/sifive/unmatched/pwm.c
new file mode 100644
index 0000000000..e1cc02310a
--- /dev/null
+++ b/board/sifive/unmatched/pwm.c
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2021, SiFive Inc
+ *
+ * Authors:
+ *   Vincent Chen <vincent.chen@sifive.com>
+ *   David Abdurachmanov <david.abdurachmanov@sifive.com>
+ */
+
+#include <linux/io.h>
+#include <asm/arch/eeprom.h>
+
+struct pwm_sifive_regs {
+	unsigned int cfg;	/* PWM configuration register */
+	unsigned int pad0;	/* Reserved */
+	unsigned int cnt;	/* PWM count register */
+	unsigned int pad1;	/* Reserved */
+	unsigned int pwms;	/* Scaled PWM count register */
+	unsigned int pad2;	/* Reserved */
+	unsigned int pad3;	/* Reserved */
+	unsigned int pad4;	/* Reserved */
+	unsigned int cmp0;	/* PWM 0 compare register */
+	unsigned int cmp1;	/* PWM 1 compare register */
+	unsigned int cmp2;	/* PWM 2 compare register */
+	unsigned int cmp3;	/* PWM 3 compare register */
+};
+
+#define PWM0_BASE		0x10020000
+#define PWM1_BASE		0x10021000
+#define PWM_CFG_INIT		0x1000
+#define PWM_CMP_ENABLE_VAL	0x0
+#define PWM_CMP_DISABLE_VAL	0xffff
+
+void pwm_device_init(void)
+{
+	struct pwm_sifive_regs *pwm0, *pwm1;
+	pwm0 = (struct pwm_sifive_regs *)PWM0_BASE;
+	pwm1 = (struct pwm_sifive_regs *)PWM1_BASE;
+	writel(PWM_CMP_DISABLE_VAL, (void *)&pwm0->cmp0);
+	/* Set the 3-color PWM LEDs to yellow in SPL */
+	writel(PWM_CMP_ENABLE_VAL, (void *)&pwm0->cmp1);
+	writel(PWM_CMP_ENABLE_VAL, (void *)&pwm0->cmp2);
+	writel(PWM_CMP_DISABLE_VAL, (void *)&pwm0->cmp3);
+	writel(PWM_CFG_INIT, (void *)&pwm0->cfg);
+
+	writel(PWM_CMP_DISABLE_VAL, (void *)&pwm0->cmp3);
+	/* Turn on all the fans, (J21), (J23) and (J24), on the unmatched board */
+	/* The SoC fan(J21) on the rev3 board cannot be controled by PWM_COMP0,
+	   so here sets the initial value of PWM_COMP0 as DISABLE */
+	if (get_pcb_revision_from_eeprom() == PCB_REVISION_REV3)
+		writel(PWM_CMP_DISABLE_VAL, (void *)&pwm1->cmp1);
+	else
+		writel(PWM_CMP_ENABLE_VAL, (void *)&pwm1->cmp1);
+	writel(PWM_CMP_ENABLE_VAL, (void *)&pwm1->cmp2);
+	writel(PWM_CMP_ENABLE_VAL, (void *)&pwm1->cmp3);
+	writel(PWM_CFG_INIT, (void *)&pwm1->cfg);
+}
diff --git a/board/sifive/unmatched/spl.c b/board/sifive/unmatched/spl.c
index 7c0beedc08..f3a661a81e 100644
--- a/board/sifive/unmatched/spl.c
+++ b/board/sifive/unmatched/spl.c
@@ -90,6 +90,8 @@ int spl_board_init_f(void)
 		goto end;
 	}
 
+	pwm_device_init();
+
 	ret = spl_gemgxl_init();
 	if (ret) {
 		debug("Gigabit ethernet PHY (VSC8541) init failed: %d\n", ret);
-- 
2.27.0

